//! # 链路驱动层
//!
//! 链路驱动层(link)规定了链路实例(Link)

pub mod frame;
mod recver;

use crate::consts::*;
use core::fmt::{self, Write};
use core::sync::atomic::{AtomicUsize, Ordering};
use frame::load2frame;
use heapless::LinearMap;
use heapless::String;
use log::{info, warn};
use recver::Recver;
use spin::Lazy;
use spin::{Mutex, RwLock};

static LINKS: Lazy<RwLock<LinearMap<Link, Driver, LinkLen>>> =
    Lazy::new(|| RwLock::new(LinearMap::new()));
static RECVERS: Lazy<Mutex<LinearMap<Link, Recver, RecverLen>>> =
    Lazy::new(|| Mutex::new(LinearMap::new()));
static HANDLE_SN: AtomicUsize = AtomicUsize::new(1);

/// 错误类型
#[derive(Debug)]
pub enum ErrorKind {
    /// 链路不存在
    NotFound,
    /// 链路已断开
    NotConnected,
    /// 发送超时
    TimedOut,
    /// 需要异步执行
    WouldBlock,
    /// 待发送的数据错误
    InvalidData,
}
type SendDriver = fn(link: &Link, buf: &[u8]) -> Result<(), ErrorKind>;
/// 链路驱动接口
struct Driver {
    /// 链路唯一ID
    uid: String<UidLen>,
    /// 数据发送接口
    sendto: SendDriver,
}

/// 链路实例描述符(Link)
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Link {
    handle: usize,
}
impl fmt::Display for Link {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "link{}", self.handle)
    }
}
impl Link {
    /// 通过链路驱动接口(Driver)创建链路实例
    pub fn new(uid_args: fmt::Arguments, sendto: SendDriver) -> Self {
        let mut uid = String::<UidLen>::new();
        let _err = uid.write_fmt(uid_args);
        for (link, driver) in LINKS.write().iter_mut() {
            if driver.uid == uid {
                info!("{} had reinit.", uid);
                driver.sendto = sendto;
                return *link;
            }
        }
        let link = Link {
            handle: HANDLE_SN.fetch_add(1, Ordering::Relaxed),
        };
        let driver = Driver {
            uid: uid,
            sendto: sendto,
        };
        if let Err(_) = LINKS.write().insert(link, driver) {
            panic!("too many link.");
        };
        link
    }
    /// 通过链路唯一ID查找链路实例
    pub fn find(uid_args: fmt::Arguments) -> Option<Self> {
        let mut uid = String::<UidLen>::new();
        let _err = uid.write_fmt(uid_args);
        for (link, driver) in LINKS.read().iter() {
            if driver.uid == uid {
                return Some(*link);
            }
        }
        None
    }
    /// 从链路池中销毁链路
    pub fn destroy(self) {
        LINKS.write().remove(&self);
        RECVERS.lock().remove(&self);
    }
    /// 本链路是否在链路池中存活
    pub fn has(&self) -> bool {
        for (link, _driver) in LINKS.read().iter() {
            if link == self {
                return true;
            }
        }
        false
    }
    /// 打印链路池uid
    pub fn info() {
        info!("print link uid.");
        for (link, driver) in LINKS.read().iter() {
            info!("link{} uid: {}.", link.handle, driver.uid);
        }
    }
    /// 调用链路实例发送负载数据
    pub fn send(&self, buf: &[u8]) -> Result<(), ErrorKind> {
        let links = LINKS.read();
        let driver = {
            if let Some(driver) = links.get(self) {
                driver
            } else {
                return Err(ErrorKind::NotFound);
            }
        };
        let frame = load2frame(buf);
        if let Ok(frame) = frame {
            match (driver.sendto)(self, &frame) {
                Ok(_) => {
                    info!("{} send:{:02X?}.", driver.uid, buf);
                    return Ok(());
                }
                Err(ErrorKind::NotConnected) => {
                    drop(driver);
                    drop(links);
                    (*self).destroy();
                    return Err(ErrorKind::NotFound);
                }
                Err(ErrorKind::TimedOut) => {
                    return Err(ErrorKind::TimedOut);
                }
                Err(ErrorKind::WouldBlock) => {
                    return Err(ErrorKind::WouldBlock);
                }
                Err(err) => {
                    warn!("unmp link send err:{:?}", err);
                    return Err(err);
                }
            }
        } else {
            warn!("{:?}", frame);
            return Err(ErrorKind::InvalidData);
        }
    }
    /// 广播负载数据到链路池中所有链路
    pub fn broadcast(buf: &[u8]) {
        let frame = load2frame(buf);
        let frame = if let Ok(frame) = frame {
            info!("broadcast:{:02X?}.", buf);
            frame
        } else {
            warn!("{:?}", frame);
            return;
        };
        for (link, driver) in LINKS.read().iter() {
            let _err = (driver.sendto)(link, &frame);
        }
    }
    /// 接收字节流数据帧，并返回负载数据。务必确保buf的长度小于FrameLen
    pub fn recv(&self, buf: &[u8], load: &mut [u8]) -> usize {
        let mut recvers = RECVERS.lock();
        if let Some(recver) = recvers.get_mut(self) {
            let num = recver.recv(buf, load);
            if !recver.is_empty() {
            } else {
                recvers.remove(self);
            }
            return num;
        }
        if !self.has() {
            return 0;
        }
        let mut recver = Recver::new();
        let num = recver.recv(buf, load);
        if !recver.is_empty() {
            let _err = recvers.insert(*self, recver);
        }
        return num;
    }
}
